package cn.wolfcode.exception;

import cn.wolfcode.domain.JsonResult;
import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 该注解表示被贴的类会对控制器进行增强的,类似于事务增强
 */
@ControllerAdvice
public class MyControllerAdvice {
    /**
     * 该注解表示被贴的方法会自动捕获控制器出现的指定异常,并在方法内进行处理
     * 注解的()内可以写指定的异常,一般最大写RuntimeException
     */
    @ExceptionHandler(RuntimeException.class)
    public String catchRuntimeException(RuntimeException e, HttpServletResponse response, HandlerMethod handlerMethod){
        //捕获到异常后先打印,方便后续找bug
        e.printStackTrace();

        //判断出现异常的方法是否有ResponseBody注解,有就代表需要返回JsonResult对象,无则直接放回视图
        if(handlerMethod.hasMethodAnnotation(ResponseBody.class)){
            //有注解,则是void或者是需要返回自定义类对象获取
            JsonResult jsonResult = new JsonResult(false,"系统异常");
            try {
                //响应需要编码
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println(JSON.toJSONString(jsonResult));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            //直接response回去了,所以此处返回null
            return null;
        }else {
            //捕获到异常需要返回错误的页面
            return "common/error";
        }
    }

    //专门用于捕获自定义的LogicException异常,多个异常会优先匹配精准的,然后再匹配父类的
    @ExceptionHandler(LogicException.class)
    @ResponseBody
    public JsonResult catchLogicException(LogicException e){
        //由于这边自定义的异常都是返回一个信息的,即JsonResult类,因此不再判断是返回自定义类还是视图
        //且由于这个返回了e.getMessage(),一般可以知道是什么异常(一般也是用户才会导致的异常),所以不再打印异常
        return new JsonResult(false,e.getMessage());
    }
}
